package auth

import (
	"fmt"
	"net/http"
	"strings"

	"apiGateWay/internal/auth/jwt"
	"apiGateWay/internal/auth/oauth2"
	"apiGateWay/internal/config"
	"apiGateWay/internal/database"
	"apiGateWay/pkg/logger"

	"github.com/gin-gonic/gin"
)

var (
	jwtManager *jwt.JWTManager
	oauth2Manager *oauth2.OAuth2Manager
)

// Init 初始化认证模块
func Init(cfg *config.Config) {
	jwtManager = jwt.NewJWTManager(
		cfg.JWT.Secret,
		cfg.JWT.Issuer,
		cfg.JWT.Expiration,
	)

	if cfg.OAuth2.Enabled {
		oauth2Manager = oauth2.NewOAuth2Manager()
		for name, provider := range cfg.OAuth2.Providers {
			oauth2Manager.RegisterProvider(
				name,
				provider.ClientID,
				provider.ClientSecret,
				provider.RedirectURL,
			)
		}
	}

	// 初始化用户仓库
	if cfg.Database.Enabled && database.DB != nil {
		InitUserRepository()
	}
}

// JWTAuthMiddleware JWT 认证中间件
func JWTAuthMiddleware(cfg *config.Config) gin.HandlerFunc {
	if jwtManager == nil {
		jwtManager = jwt.NewJWTManager(
			cfg.JWT.Secret,
			cfg.JWT.Issuer,
			cfg.JWT.Expiration,
		)
	}

	return func(c *gin.Context) {
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			c.JSON(http.StatusUnauthorized, gin.H{
				"error": "缺少 Authorization 头",
			})
			c.Abort()
			return
		}

		// 提取 Bearer token
		parts := strings.SplitN(authHeader, " ", 2)
		if len(parts) != 2 || parts[0] != "Bearer" {
			c.JSON(http.StatusUnauthorized, gin.H{
				"error": "无效的 Authorization 格式",
			})
			c.Abort()
			return
		}

		token := parts[1]
		claims, err := jwtManager.ValidateToken(token)
		if err != nil {
			c.JSON(http.StatusUnauthorized, gin.H{
				"error": "无效的令牌",
			})
			c.Abort()
			return
		}

		// 将用户信息存储到上下文中
		c.Set("user_id", claims.UserID)
		c.Set("username", claims.Username)
		c.Set("email", claims.Email)
		c.Next()
	}
}

// LoginHandler 登录处理器
func LoginHandler(cfg *config.Config) gin.HandlerFunc {
	if jwtManager == nil {
		jwtManager = jwt.NewJWTManager(
			cfg.JWT.Secret,
			cfg.JWT.Issuer,
			cfg.JWT.Expiration,
		)
	}

	return func(c *gin.Context) {
		var req struct {
			Username string `json:"username" binding:"required"`
			Password string `json:"password" binding:"required"`
		}

		if err := c.ShouldBindJSON(&req); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": "无效的请求参数",
			})
			return
		}

		// 验证用户名和密码
		if req.Username == "" || req.Password == "" {
			c.JSON(http.StatusUnauthorized, gin.H{
				"error": "用户名或密码不能为空",
			})
			return
		}

		// 如果启用了数据库，必须从数据库验证
		if cfg.Database.Enabled {
			if database.DB == nil {
				c.JSON(http.StatusInternalServerError, gin.H{
					"error": "数据库未初始化",
				})
				return
			}

			user, err := VerifyUser(req.Username, req.Password)
			if err != nil {
				c.JSON(http.StatusUnauthorized, gin.H{
					"error": "用户名或密码错误",
				})
				return
			}
			
			// 使用数据库中的用户信息生成令牌
			accessToken, err := jwtManager.GenerateToken(
				fmt.Sprintf("%d", user.ID),
				user.Username,
				user.Email,
			)
			if err != nil {
				logger.Errorf("生成令牌失败: %v", err)
				c.JSON(http.StatusInternalServerError, gin.H{
					"error": "生成令牌失败",
				})
				return
			}

			refreshToken, err := jwtManager.GenerateRefreshToken(
				fmt.Sprintf("%d", user.ID),
				int(cfg.JWT.RefreshExpiration),
			)
			if err != nil {
				logger.Errorf("生成刷新令牌失败: %v", err)
				c.JSON(http.StatusInternalServerError, gin.H{
					"error": "生成刷新令牌失败",
				})
				return
			}

			UpdateLastLogin(user.ID)

			c.JSON(http.StatusOK, gin.H{
				"access_token":  accessToken,
				"refresh_token": refreshToken,
				"token_type":    "Bearer",
				"expires_in":    cfg.JWT.Expiration,
				"user": gin.H{
					"id":       fmt.Sprintf("%d", user.ID),
					"username": user.Username,
					"email":    user.Email,
					"is_admin": user.IsAdmin,
				},
			})
			return
		}
		
		// 数据库未启用时，降级到固定账号密码验证（仅用于开发测试）
		validUsername := "admin"
		validPassword := "admin123"
		
		if req.Username != validUsername || req.Password != validPassword {
			c.JSON(http.StatusUnauthorized, gin.H{
				"error": "用户名或密码错误",
			})
			return
		}

		// 生成令牌
		accessToken, err := jwtManager.GenerateToken("user-123", req.Username, req.Username+"@example.com")
		if err != nil {
			logger.Errorf("生成令牌失败: %v", err)
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成令牌失败",
			})
			return
		}

		refreshToken, err := jwtManager.GenerateRefreshToken("user-123", cfg.JWT.RefreshExpiration)
		if err != nil {
			logger.Errorf("生成刷新令牌失败: %v", err)
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成刷新令牌失败",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"access_token":  accessToken,
			"refresh_token": refreshToken,
			"token_type":    "Bearer",
			"expires_in":    cfg.JWT.Expiration,
			"user": gin.H{
				"id":       "user-123",
				"username": req.Username,
				"email":    req.Username + "@example.com",
				"is_admin": false,
			},
		})
	}
}

// RefreshTokenHandler 刷新令牌处理器
func RefreshTokenHandler(cfg *config.Config) gin.HandlerFunc {
	if jwtManager == nil {
		jwtManager = jwt.NewJWTManager(
			cfg.JWT.Secret,
			cfg.JWT.Issuer,
			cfg.JWT.Expiration,
		)
	}

	return func(c *gin.Context) {
		var req struct {
			RefreshToken string `json:"refresh_token" binding:"required"`
		}

		if err := c.ShouldBindJSON(&req); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": "无效的请求参数",
			})
			return
		}

		accessToken, newRefreshToken, err := jwtManager.RefreshToken(req.RefreshToken)
		if err != nil {
			c.JSON(http.StatusUnauthorized, gin.H{
				"error": "刷新令牌失败",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"access_token":  accessToken,
			"refresh_token": newRefreshToken,
			"token_type":    "Bearer",
			"expires_in":    cfg.JWT.Expiration,
		})
	}
}

// OAuth2LoginHandler OAuth2 登录处理器
func OAuth2LoginHandler(cfg *config.Config) gin.HandlerFunc {
	if !cfg.OAuth2.Enabled {
		return func(c *gin.Context) {
			c.JSON(http.StatusServiceUnavailable, gin.H{
				"error": "OAuth2 未启用",
			})
		}
	}

	if oauth2Manager == nil {
		oauth2Manager = oauth2.NewOAuth2Manager()
		for name, provider := range cfg.OAuth2.Providers {
			oauth2Manager.RegisterProvider(
				name,
				provider.ClientID,
				provider.ClientSecret,
				provider.RedirectURL,
			)
		}
	}

	return func(c *gin.Context) {
		provider := c.Param("provider")
		authURL, err := oauth2Manager.GetAuthURL(provider)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
			return
		}

		c.Redirect(http.StatusTemporaryRedirect, authURL)
	}
}

// OAuth2CallbackHandler OAuth2 回调处理器
func OAuth2CallbackHandler(cfg *config.Config) gin.HandlerFunc {
	if !cfg.OAuth2.Enabled {
		return func(c *gin.Context) {
			c.JSON(http.StatusServiceUnavailable, gin.H{
				"error": "OAuth2 未启用",
			})
		}
	}

	if jwtManager == nil {
		jwtManager = jwt.NewJWTManager(
			cfg.JWT.Secret,
			cfg.JWT.Issuer,
			cfg.JWT.Expiration,
		)
	}

	if oauth2Manager == nil {
		oauth2Manager = oauth2.NewOAuth2Manager()
		for name, provider := range cfg.OAuth2.Providers {
			oauth2Manager.RegisterProvider(
				name,
				provider.ClientID,
				provider.ClientSecret,
				provider.RedirectURL,
			)
		}
	}

	return func(c *gin.Context) {
		provider := c.Param("provider")
		code := c.Query("code")
		state := c.Query("state")

		if code == "" {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": "缺少授权码",
			})
			return
		}

		// 交换授权码
		token, err := oauth2Manager.ExchangeCode(provider, code, state)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": "交换令牌失败: " + err.Error(),
			})
			return
		}

		// 获取用户信息
		userInfo, err := oauth2Manager.GetUserInfo(provider, token)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "获取用户信息失败: " + err.Error(),
			})
			return
		}

		// 生成 JWT 令牌
		accessToken, err := jwtManager.GenerateToken(userInfo.ID, userInfo.Username, userInfo.Email)
		if err != nil {
			logger.Errorf("生成令牌失败: %v", err)
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成令牌失败",
			})
			return
		}

		refreshToken, err := jwtManager.GenerateRefreshToken(userInfo.ID, cfg.JWT.RefreshExpiration)
		if err != nil {
			logger.Errorf("生成刷新令牌失败: %v", err)
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "生成刷新令牌失败",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"access_token":  accessToken,
			"refresh_token": refreshToken,
			"token_type":    "Bearer",
			"expires_in":    cfg.JWT.Expiration,
			"user":          userInfo,
		})
	}
}

